import json
from typing import Optional, List

from bct.tools.common.bct4.base_dto import JsonDTO
# 雪球观察日
from bct.tools.http.trade.bct4_trade_dto import Product, KnockInFeature, KnockInPriceType, \
    KnockOutPaymentTypeEnum, TradeDTO, DirectionTypeEnum, ProductTypeEnum


class SnowballObservationDTO(JsonDTO):
    coupon_price: Optional[str] = None
    # 敲出收益率
    knock_out_coupon_rate: Optional[str] = None
    # 敲出价格系数
    knock_out_price_ratio: Optional[str] = None
    # 敲出价格
    knock_out_price: Optional[str] = None
    # 敲出观察日
    knock_out_observation_date: Optional[str] = None
    # 敲出结算日
    knock_out_settlement_date: Optional[str] = None
    # 敲出计算天数
    knock_out_counted_days: Optional[int] = None

    def to_dict(self):
        return {
            "couponPrice": self.coupon_price,
            "knockOutPriceRatio": self.knock_out_price_ratio,
            "knockOutCouponRate": self.knock_out_coupon_rate,
            "knockOutPrice": self.knock_out_price,
            "knockOutObservationDate": self.knock_out_observation_date,
            "knockOutSettlementDate": self.knock_out_settlement_date,
            "knockOutCountedDays": self.knock_out_counted_days,
        }


# 非保本雪球
class ObservationFeature(JsonDTO):
    # 期末观察日
    last_observation_date: str
    # 观察日列表
    observations: List[SnowballObservationDTO] = list()

    def to_dict(self):
        observ_list = []
        for o in self.observations:
            observ_list.append(o.to_dict())
        return {
            "lastObservationDate": self.last_observation_date,
            "observations": observ_list
        }


class SnowballFloatingNone(Product, KnockInFeature, ObservationFeature):
    knock_out_price_type: KnockInPriceType = KnockInPriceType.CLOSE
    # 敲出支付类型
    knock_out_payment_type: KnockOutPaymentTypeEnum
    # 敲出价格系数 12位整数和8位小数
    knock_out_price_ratio: str
    # 敲出价格逐级调整系数 非必填：%，默认0.00%
    knock_out_price_step_by_step_adjustment_ratio: str
    # 敲出收益率
    knock_out_coupon_rate: str
    # 红利票息 必填：不能为负数，%
    snow_ball_coupon_rate: str

    def to_dict(self):
        json_obj = Product.to_dict(self)
        knock_in_obj = KnockInFeature.to_dict(self)
        observation_obj = ObservationFeature.to_dict(self)
        json_obj.update(knock_in_obj)
        json_obj.update(observation_obj)
        json_obj['knockOutPaymentType'] = self.knock_out_payment_type.value
        json_obj['knockOutPriceType'] = self.knock_out_price_type.value
        json_obj['knockOutPriceRatio'] = self.knock_out_price_ratio
        json_obj['knockOutPriceStepByStepAdjustmentRatio'] = self.knock_out_price_step_by_step_adjustment_ratio
        json_obj['knockOutCouponRate'] = self.knock_out_coupon_rate
        json_obj['snowBallCouponRate'] = self.snow_ball_coupon_rate
        return json_obj


if __name__ == '__main__':
    obj = SnowballFloatingNone()
    obj.initial_date = "2020-10-10"
    obj.knock_out_payment_type = KnockOutPaymentTypeEnum.due_payment
    obj.participation = "0.98"
    obj.instrument_id = "000001.SZ"
    obj.instrument_name = "平安银行"
    obj.settlement_date = "2021-11-02"
    obj.counted_days = 8
    obj.initial_price = "100"
    obj.strike_price = "100"
    obj.last_observation_date = "2021-10-29"
    obj.initial_premium_rate = '0.11'
    obj.initial_premium_payment_date = '2021-10-25'
    obj.initial_premium = '24.11'
    obj.notional = 10000
    obj.product_type = ProductTypeEnum.SNOWBALL_FLOATING_NONE

    obj.knock_out_price_ratio = "0.008"
    obj.knock_out_price_step_by_step_adjustment_ratio = "0.0002"
    obj.knock_out_coupon_rate = "0.18"
    # 观察日
    obj.observations = []
    observation_day_1 = SnowballObservationDTO()
    observation_day_1.knock_out_price_ratio = "0.0074"
    observation_day_1.knock_out_coupon_rate = "0.18"
    observation_day_1.knock_out_price = "0.74"
    observation_day_1.knock_out_observation_date = "2021-10-29"
    observation_day_1.knock_out_settlement_date = "2021-11-02"
    observation_day_1.knock_out_counted_days = 8
    obj.observations.append(observation_day_1)

    obj.knock_in_price = "80"
    obj.knock_in_price_ratio = "0.8"

    trade = TradeDTO()
    trade.products = []
    trade.products.append(obj)
    trade.direction = DirectionTypeEnum.BUYER
    trade.trade_id = "sc_001"
    trade.book_name = "TEST1"
    trade.capital_account_name = "capitalAccountName"
    trade.counterparty_name = "ct1"
    trade.initial_date = "2021-11-01"
    trade.trade_date = "2021-11-01"
    trade.last_observation_date = "2021-11-13"
    trade.notional = '10000'
    trade.initial_x_rate = '1'
    trade.initial_premium = '24.11'
    trade.initial_premium_rate = '0.11'
    trade.initial_premium_payment_date = '2021-11-01'
    trade.counted_days = 8

    print(json.dumps(trade.to_dict()))
